/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.cvut.fel.taskpro.data.manager;


import cz.cvut.fel.taskpro.data.entity.GroupTaskPro;
import cz.cvut.fel.taskpro.data.entity.Kantor;
import cz.cvut.fel.taskpro.data.entity.Student;
import cz.cvut.fel.taskpro.data.entity.Subject;
import cz.cvut.fel.taskpro.data.entity.Team;
import cz.cvut.fel.taskpro.data.imanager.ISubjectData;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;


/**
 * This class implement #{@link ISubjectData} interface
 * @author Tom
 * @version 1.0. beta
 */
@Stateless
public class SubjectData extends ObjectManager implements ISubjectData {

    @Override
    public void addSubject(Subject subject) {
        super.add(subject);
    }

    
    @Override
    public Subject getSubjectByCode(String code) {
        Query q = em.createNamedQuery("Subject.findByCode");
        q.setParameter("code", code);
        List<Subject> results=q.getResultList();
        if(!results.isEmpty()){
            return results.get(0);
        }
        return null;
    }

    @Override
    public List<Subject> getAllSubject() {
        Query q = em.createNamedQuery("Subject.all");
        List<Subject> lp = q.getResultList();
        for (Subject predmet : lp) {
            List<GroupTaskPro> m_paralelka = predmet.getmGroups();
            for (GroupTaskPro paralelka : m_paralelka) {
                paralelka = (GroupTaskPro) refresh(paralelka);
                Kantor kantor = paralelka.getKantor();
                kantor=(Kantor) refresh(kantor);         
                List<Team> m_skupina = paralelka.getmTeams();
                for (Team skupina : m_skupina) {
                    skupina = (Team) refresh(skupina);
                }
                List<Student> mStudents = paralelka.getMStudents();
                for (Student student : mStudents) {
                    student = (Student) refresh(student);
                }
            }
        }
        return lp;
    }

    @Override
    public void updateSubject(Subject subject) {
        super.update(subject);
    }

    @Override
    public List<Subject> getSubjecByKantor(Kantor kantor) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Subject> querySubject = cb.createQuery(Subject.class);
        Root<Subject> querySubjectRoot = querySubject.from(Subject.class);
        Join<Subject, GroupTaskPro> subjectInGroup = querySubjectRoot.join("mGroups");
        Join<GroupTaskPro, Kantor> kantorInGroup = subjectInGroup.join("kantor");
        Predicate kantorPred = cb.equal(kantorInGroup, kantor);
        querySubject.where(kantorPred).distinct(true).orderBy(cb.desc(querySubjectRoot.get("code")));
        TypedQuery typedQuery = em.createQuery(querySubject);
        List<Subject> result = typedQuery.getResultList();
        return result;
    }

    @Override
    public List<Student> getStudentsInSubject(Subject subject) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Student> queryStudent = cb.createQuery(Student.class);
        Root<Student> rootStudent = queryStudent.from(Student.class);
        Join<Student, GroupTaskPro> studentGroup = rootStudent.join("mGroups");
        Predicate subjectPredicate = cb.equal(studentGroup.get("subject"), subject);
        queryStudent.where(subjectPredicate);
        queryStudent.distinct(true);
        queryStudent.orderBy(cb.asc(rootStudent.get("login")));
        TypedQuery typedQuery = em.createQuery(queryStudent);
        List<Student> resultList = typedQuery.getResultList();
        return resultList;
    }

    @Override
    public List<Subject> getStudentsSubject(Student student) {
        CriteriaBuilder cb=em.getCriteriaBuilder();
        CriteriaQuery<Subject> querySubject=cb.createQuery(Subject.class);
        Root<Subject> querySubjectRott=querySubject.from(Subject.class);
        Join<Subject,GroupTaskPro> groupSubject=querySubjectRott.join("mGroups");
        Join<GroupTaskPro,Student> studentGroup=groupSubject.join("mStudents");
        Predicate studentPred=cb.equal(studentGroup, student);
        querySubject.select(querySubjectRott);
        querySubject.distinct(true).orderBy(cb.asc(querySubjectRott.get("code"))).where(studentPred);
        TypedQuery typedQuery=em.createQuery(querySubject);
        List<Subject> resultList=typedQuery.getResultList();
        return resultList;
    }

    @Override
    public void refreshAllSubjects(Subject subjectToRefresh) {
            List<GroupTaskPro> mGroup = subjectToRefresh.getmGroups();
            for (GroupTaskPro group : mGroup) {
                group = (GroupTaskPro) super.refresh(group);
                              Kantor kantor = group.getKantor();
                kantor=(Kantor) super.refresh(kantor); 
                List<Team> mTeam = group.getmTeams();
                for (Team team : mTeam) {
                    team = (Team) super.refresh(team);
                }
                List<Student> mStudents = group.getMStudents();
                for (Student student : mStudents) {
                    student = (Student) super.refresh(student);
                }
            }
        }
    

}
